//===============================================================================
// Microsoft patterns & practices Enterprise Library Contribution
// Policy Injection Application Block
//===============================================================================

using System;
using System.Collections.Generic;
using System.Configuration;
using System.Transactions;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration.ContainerModel;
using Microsoft.Practices.Unity.InterceptionExtension;

namespace EntLibContrib.PolicyInjection.CallHandlers.Configuration
{
	/// <summary>
	/// Transaction Scope Call Handler Data
	/// </summary>
	public class TransactionScopeCallHandlerData : CallHandlerData
	{
		#region Constants
		private const string TransactionScopeOptionPropertyName = "transactionScopeOption";
		private const string TimeoutPropertyName = "timeout";
		private const string IsolationLevelPropertyName = "isolationLevel";
		private const string EnterpriseServicesInteropOptionPropertyName = "interopOption";
		private const string CompletePropertyName = "complete";
		#endregion

		#region Properties
		/// <summary>
		/// Gets or Sets the Transaction Scope Option.
		/// </summary>
		/// <value>The "transactionScopeOption" attribute in configuration</value>
		[ConfigurationProperty(TransactionScopeOptionPropertyName, DefaultValue = "Required")]
		public TransactionScopeOption TransactionScopeOption
		{
			get { return (TransactionScopeOption)base[TransactionScopeOptionPropertyName]; }
			set { base[TransactionScopeOptionPropertyName] = value; }
		}

		/// <summary>
		/// Gets or Sets the Timeout.
		/// </summary>
		/// <value>The "timeout" attribute in configuration</value>
		[ConfigurationProperty(TimeoutPropertyName, DefaultValue = "00:01:00")]
		public TimeSpan Timeout
		{
			get { return (TimeSpan)base[TimeoutPropertyName]; }
			set { base[TimeoutPropertyName] = value; }
		}

		/// <summary>
		/// Gets or Sets the Isolation Level.
		/// </summary>
		/// <value>The "isolationLevel" attribute in configuration</value>
		[ConfigurationProperty(IsolationLevelPropertyName, DefaultValue = "Serializable")]
		public IsolationLevel IsolationLevel
		{
			get { return (IsolationLevel)base[IsolationLevelPropertyName]; }
			set { base[IsolationLevelPropertyName] = value; }
		}

		/// <summary>
		/// Gets or Sets the EnterpriseServicesInteropOption.
		/// </summary>
		/// <value>The "interopOption" attribute in configuration</value>
		[ConfigurationProperty(EnterpriseServicesInteropOptionPropertyName, DefaultValue = "None")]
		public EnterpriseServicesInteropOption InteropOption
		{
			get { return (EnterpriseServicesInteropOption)base[EnterpriseServicesInteropOptionPropertyName]; }
			set { base[EnterpriseServicesInteropOptionPropertyName] = value; }
		}

		/// <summary>
		/// Gets or Sets whether the TransactionScope will complete on success.
		/// </summary>
		/// <value>The "complete" attribute in configuration</value>
		[ConfigurationProperty(CompletePropertyName, DefaultValue = "true")]
		public bool Complete
		{
			get { return (bool)base[CompletePropertyName]; }
			set { base[CompletePropertyName] = value; }
		}
		#endregion

		#region Construction
		/// <summary>
		/// Construct a new <see cref="TransactionScopeCallHandlerData"/>.
		/// </summary>
		public TransactionScopeCallHandlerData()
		{
		}

		/// <summary>
		/// Construct a new <see cref="TransactionScopeCallHandlerData"/>.
		/// </summary>
		/// <param name="handlerName">Name of the handler.</param>

		public TransactionScopeCallHandlerData(string handlerName)
			: base(handlerName, typeof(TransactionScopeCallHandler))
		{
		}

		/// <summary>
		/// Construct a new <see cref="TransactionScopeCallHandlerData"/>.
		/// </summary>
		/// <param name="handlerName">Name of the handler.</param>
		/// <param name="handlerOrder">The handler order.</param>
		public TransactionScopeCallHandlerData(string handlerName, int handlerOrder)
			: base(handlerName, typeof(TransactionScopeCallHandler))
		{
			Order = handlerOrder;
		}
		#endregion

		#region Public Methods
		/// <summary>
		/// Get the set of <see cref="TypeRegistration"/> objects needed to
		/// register the call handler represented by this config element and its associated objects.
		/// </summary>
		/// <param name="nameSuffix">A suffix for the names in the generated type registration objects.</param>
		/// <returns>The set of <see cref="TypeRegistration"/> objects.</returns>
		public override IEnumerable<TypeRegistration> GetRegistrations(string nameSuffix)
		{
			yield return
				new TypeRegistration<ICallHandler>(
					() => new TransactionScopeCallHandler(
						TransactionScopeOption,
						new TransactionOptions { IsolationLevel = IsolationLevel, Timeout = Timeout },
						InteropOption,
						Complete))
				{
					Name = this.Name + nameSuffix,
					Lifetime = TypeRegistrationLifetime.Transient
				};
		}
		#endregion
	}
}
